#include "tests.h"

TEST(VectorTest, DefaultConstructor_EmptyVector) {
  s21::vector<int> v;

  EXPECT_TRUE(v.empty());
}

TEST(VectorTest, SizeConstructor_ZeroSize) {
  const size_t size = 0;
  s21::vector<int> v(size);

  EXPECT_TRUE(v.empty());
}

TEST(VectorTest, SizeConstructor_PositiveSize) {
  const size_t size = 5;
  s21::vector<int> v(size);

  EXPECT_EQ(v.size(), size);
}

TEST(VectorTest, InitializerListConstructor_EmptyList) {
  s21::vector<int> v = {};

  EXPECT_TRUE(v.empty());
}

TEST(VectorTest, InitializerListConstructor_NonEmptyList) {
  s21::vector<int> v = {1, 2, 3, 4, 5};

  EXPECT_EQ(v.size(), 5);
  EXPECT_EQ(v[0], 1);
  EXPECT_EQ(v[4], 5);
}

TEST(VectorTest, CopyConstructor_EmptyVector) {
  s21::vector<int> v1;
  s21::vector<int> v2(v1);

  EXPECT_TRUE(v2.empty());
}

TEST(VectorTest, CopyConstructor_NonEmptyVector) {
  s21::vector<int> v1 = {1, 2, 3};
  s21::vector<int> v2(v1);

  EXPECT_EQ(v2.size(), v1.size());
  for (size_t i = 0; i < v1.size(); ++i) {
    EXPECT_EQ(v2[i], v1[i]);
  }
}

TEST(VectorTest, MoveConstructor_EmptyVector) {
  s21::vector<int> v1;
  s21::vector<int> v2(std::move(v1));

  EXPECT_TRUE(v2.empty());
}

TEST(VectorTest, MoveConstructor_NonEmptyVector) {
  s21::vector<int> v1 = {1, 2, 3};
  s21::vector<int> v2(std::move(v1));

  EXPECT_EQ(v2.size(), 3);
  EXPECT_TRUE(v1.empty());
}

TEST(VectorTest, CopyAssignmentOperator_NonEmptyToEmpty) {
  s21::vector<int> v1 = {1, 2, 3};
  s21::vector<int> v2;

  v2 = v1;

  EXPECT_EQ(v2.size(), v1.size());
  for (size_t i = 0; i < v1.size(); ++i) {
    EXPECT_EQ(v2[i], v1[i]);
  }
}

TEST(VectorTest, CopyAssignmentOperator_EmptyToNonEmpty) {
  s21::vector<int> v1;
  s21::vector<int> v2 = {4, 5, 6};

  v2 = v1;

  EXPECT_TRUE(v1.empty());
  EXPECT_TRUE(v2.empty());
}

TEST(VectorTest, CopyAssignmentOperator_NonEmptyToNonEmpty) {
  s21::vector<int> v1 = {1, 2, 3};
  s21::vector<int> v2 = {4, 5, 6, 7, 8};

  v2 = v1;

  EXPECT_EQ(v2.size(), v1.size());
  for (size_t i = 0; i < v1.size(); ++i) {
    EXPECT_EQ(v2[i], v1[i]);
  }
}

TEST(VectorTest, MoveAssignmentOperator_NonEmptyToEmpty) {
  s21::vector<int> v1 = {1, 2, 3};
  s21::vector<int> v2;

  v2 = std::move(v1);

  EXPECT_EQ(v2.size(), 3);
  EXPECT_TRUE(v1.empty());
}

TEST(VectorTest, MoveAssignmentOperator_EmptyToNonEmpty) {
  s21::vector<int> v1;
  s21::vector<int> v2 = {4, 5, 6};

  v2 = std::move(v1);

  EXPECT_TRUE(v1.empty());
  EXPECT_TRUE(v2.empty());
}

TEST(VectorTest, MoveAssignmentOperator_NonEmptyToNonEmpty) {
  s21::vector<int> v1 = {1, 2, 3};
  s21::vector<int> v2 = {4, 5, 6, 7, 8};

  v2 = std::move(v1);

  EXPECT_EQ(v2.size(), 3);
  EXPECT_TRUE(v1.empty());
}

TEST(VectorTest, At_ValidIndex) {
  s21::vector<int> v = {1, 2, 3, 4, 5};

  EXPECT_EQ(v.at(0), 1);
  EXPECT_EQ(v.at(4), 5);
}

TEST(VectorTest, At_InvalidIndex) {
  s21::vector<int> v = {1, 2, 3, 4, 5};

  EXPECT_THROW(v.at(5), std::out_of_range);
}

TEST(VectorTest, ConstAt_ValidIndex) {
  const s21::vector<int> v = {1, 2, 3, 4, 5};

  EXPECT_EQ(v.at(2), 3);
  EXPECT_EQ(v.at(3), 4);
}

TEST(VectorTest, ConstAt_InvalidIndex) {
  const s21::vector<int> v = {1, 2, 3, 4, 5};

  EXPECT_THROW(v.at(9), std::out_of_range);
}

TEST(VectorTest, IndexOperator) {
  s21::vector<int> v = {1, 2, 3, 4, 5};

  EXPECT_EQ(v[1], 2);
  EXPECT_EQ(v[4], 5);
}

TEST(VectorTest, ConstIndexOperator) {
  const s21::vector<int> v = {1, 2, 3, 4, 5};

  EXPECT_EQ(v[0], 1);
  EXPECT_EQ(v[3], 4);
}

TEST(VectorTest, FrontConst) {
  const s21::vector<int> v = {1, 2, 3, 4, 5};

  EXPECT_EQ(v.front(), 1);
}

TEST(VectorTest, BackConst) {
  const s21::vector<int> v = {1, 2, 3, 4, 5};

  EXPECT_EQ(v.back(), 5);
}

TEST(VectorTest, Data_EmptyVector) {
  s21::vector<int> v;

  int* data_ptr = v.data();

  EXPECT_EQ(data_ptr, nullptr);
}

TEST(VectorTest, Data_ValidVector) {
  s21::vector<int> v = {1, 2, 3, 4, 5};

  int* data_ptr = v.data();
  EXPECT_EQ(*data_ptr, 1);
}

TEST(VectorTest, Begin_End_EmptyVector) {
  s21::vector<int> v;

  EXPECT_EQ(v.begin(), v.end());
}

TEST(VectorTest, Begin_ValidVector) {
  s21::vector<int> v = {1, 2, 3, 4, 5};

  auto it = v.begin();

  EXPECT_EQ(*it, 1);
}

TEST(VectorTest, End_ValidVector) {
  s21::vector<int> v = {1, 2, 3};

  EXPECT_EQ(v.end() - v.begin(), 3);
}

TEST(VectorTest, CBegin_CEnd_EmptyVector) {
  const s21::vector<int> v;

  EXPECT_EQ(v.cbegin(), v.cend());
}

TEST(VectorTest, CBegin_ValidVector) {
  const s21::vector<int> v = {1, 2, 3, 4, 5};

  auto it = v.cbegin();

  EXPECT_EQ(*it, 1);
}

TEST(VectorTest, CEnd_ValidVector) {
  const s21::vector<int> v = {1, 2};

  EXPECT_EQ(v.cend() - v.cbegin(), 2);
}

TEST(VectorTest, Empty_EmptyVector) {
  const s21::vector<int> v;

  EXPECT_TRUE(v.empty());
}

TEST(VectorTest, Empty_NonEmptyVector) {
  const s21::vector<int> v = {1, 2, 3};

  EXPECT_FALSE(v.empty());
}

TEST(VectorTest, Size_EmptyVector) {
  const s21::vector<int> v;

  EXPECT_EQ(v.size(), 0);
}

TEST(VectorTest, Size_NonEmptyVector) {
  const s21::vector<int> v = {1, 2, 3};

  EXPECT_EQ(v.size(), 3);
}

TEST(VectorTest, MaxSize) {
  const s21::vector<int> v;

  EXPECT_GT(v.max_size(), 0);
}

TEST(VectorTest, Reserve_IncreaseCapacity) {
  s21::vector<int> v;
  size_t new_capacity = 10;

  v.reserve(new_capacity);

  EXPECT_EQ(v.capacity(), new_capacity);
}

TEST(VectorTest, Reserve_DecreaseCapacity) {
  s21::vector<int> v = {1, 2, 3, 4, 5};
  size_t capacity = v.capacity();
  size_t new_capacity = capacity - 2;

  v.reserve(new_capacity);

  EXPECT_EQ(v.capacity(), capacity);
}

TEST(VectorTest, Reserve_EqualseCapacity) {
  s21::vector<int> v = {1, 2, 3, 4, 5};
  size_t new_capacity = v.capacity();
  s21::vector<int>* v_ptr = &v;

  v.reserve(new_capacity);

  EXPECT_EQ(v_ptr, &v);
}

TEST(VectorTest, Reserve_TooLargeCapacity) {
  s21::vector<int> v = {1, 2, 3, 4, 5};
  size_t new_capacity = v.max_size() + 1;

  EXPECT_THROW(v.reserve(new_capacity), std::length_error);
}

TEST(VectorTest, Capacity_EmptyVector) {
  const s21::vector<int> v;

  EXPECT_EQ(v.capacity(), 0);
}

TEST(VectorTest, Capacity_NonEmptyVector) {
  const s21::vector<int> v = {1, 2, 3};

  EXPECT_EQ(v.capacity(), v.size());
}

TEST(VectorTest, ShrinkToFit_EmptyVector) {
  s21::vector<int> v;

  v.shrink_to_fit();

  EXPECT_EQ(v.capacity(), 0);
}

TEST(VectorTest, ShrinkToFit_NonEmptyVector) {
  s21::vector<int> v = {1, 2, 3, 4, 5};
  size_t init_capacity = v.capacity();

  v.pop_back();
  v.shrink_to_fit();

  EXPECT_LT(v.capacity(), init_capacity);
}

TEST(VectorTest, Clear_EmptyVector) {
  s21::vector<int> v;

  v.clear();

  EXPECT_TRUE(v.empty());
}

TEST(VectorTest, Clear_NonEmptyVector) {
  s21::vector<int> v = {1, 2, 3, 4, 5};

  v.clear();

  EXPECT_TRUE(v.empty());
  EXPECT_EQ(v.capacity(), 5);
}

TEST(VectorTest, Insert_RV_Beginning) {
  s21::vector<int> v = {2, 3, 4};

  auto it = v.insert(v.begin(), 1);

  EXPECT_EQ(v.size(), 4);
  EXPECT_EQ(v[0], 1);
  EXPECT_EQ(*it, 1);
}

TEST(VectorTest, Insert_RV_Middle) {
  s21::vector<int> v = {1, 3, 4, 5};

  auto it = v.insert(std::next(v.begin()), 2);

  EXPECT_EQ(v.size(), 5);
  EXPECT_EQ(v[1], 2);
  EXPECT_EQ(*it, 2);
}

TEST(VectorTest, Insert_RV_End) {
  s21::vector<int> v = {1, 2};

  auto it = v.insert(v.end(), 3);

  EXPECT_EQ(v.size(), 3);
  EXPECT_EQ(v[2], 3);
  EXPECT_EQ(*it, 3);
}

TEST(VectorTest, Insert_LV_End) {
  s21::vector<int> v = {1, 2, 3, 4, 5};
  const int number = 6;

  auto it = v.insert(v.end(), number);

  EXPECT_EQ(v.size(), 6);
  EXPECT_EQ(v[5], 6);
  EXPECT_EQ(*it, 6);
}

TEST(VectorTest, Erase_Beginning) {
  s21::vector<int> v = {1, 2, 3, 4};

  v.erase(v.begin());

  EXPECT_EQ(v.size(), 3);
  EXPECT_EQ(v[0], 2);
}

TEST(VectorTest, Erase_Middle) {
  s21::vector<int> v = {1, 2, 3, 4};

  v.erase(std::next(v.begin()));

  EXPECT_EQ(v.size(), 3);
  EXPECT_EQ(v[1], 3);
}

TEST(VectorTest, Erase_End) {
  s21::vector<int> v = {1, 2, 3, 4};

  v.erase(std::prev(v.end()));

  EXPECT_EQ(v.size(), 3);
  EXPECT_EQ(v[2], 3);
}

TEST(VectorTest, PushBack_EmptyVector) {
  s21::vector<int> v;

  v.push_back(1);

  EXPECT_EQ(v.size(), 1);
  EXPECT_EQ(v[0], 1);
}

TEST(VectorTest, PushBack_NonEmptyVector) {
  s21::vector<int> v = {1, 2, 3};

  v.push_back(4);

  EXPECT_EQ(v.size(), 4);
  EXPECT_EQ(v[3], 4);
}

TEST(VectorTest, PopBack_NonEmptyVector) {
  s21::vector<int> v = {1, 2, 3};

  v.pop_back();

  EXPECT_EQ(v.size(), 2);
  EXPECT_EQ(v.back(), 2);
}

TEST(VectorTest, Swap_NonEmptyVectors) {
  s21::vector<int> v1 = {1, 2, 3};
  s21::vector<int> v2 = {4, 5, 6};

  v1.swap(v2);

  EXPECT_EQ(v1.size(), 3);
  EXPECT_EQ(v2.size(), 3);
  EXPECT_EQ(v1[0], 4);
  EXPECT_EQ(v1[2], 6);
  EXPECT_EQ(v2[0], 1);
  EXPECT_EQ(v2[2], 3);
}

TEST(VectorTest, Swap_EmptyAndNonEmptyVectors) {
  s21::vector<int> v1;
  s21::vector<int> v2 = {1, 2, 3};

  v1.swap(v2);

  EXPECT_EQ(v1.size(), 3);
  EXPECT_EQ(v1[2], 3);
  EXPECT_TRUE(v2.empty());
}

TEST(VectorTest, InsertMany) {
  s21::vector<int> v = {1, 2, 3, 7, 8};

  v.insert_many(std::next(v.cbegin(), 3), 4, 5, 6);

  EXPECT_EQ(v.size(), 8);
  EXPECT_EQ(v[2], 3);
  EXPECT_EQ(v[3], 4);
  EXPECT_EQ(v[4], 5);
  EXPECT_EQ(v[5], 6);
  EXPECT_EQ(v[6], 7);
}

TEST(VectorTest, InsertManyBack_with_reserve) {
  s21::vector<int> v = {1, 2, 3};

  v.insert_many_back(4, 5, 6);

  EXPECT_EQ(v.size(), 6);
  EXPECT_EQ(v[2], 3);
  EXPECT_EQ(v[3], 4);
  EXPECT_EQ(v[4], 5);
  EXPECT_EQ(v[5], 6);
}

TEST(VectorTest, InsertManyBack_without_reserve) {
  s21::vector<int> v = {1, 2};
  v.reserve(4);

  v.insert_many_back(3, 4);

  EXPECT_EQ(v.size(), 4);
  EXPECT_EQ(v.capacity(), 4);
  EXPECT_EQ(v[1], 2);
  EXPECT_EQ(v[2], 3);
  EXPECT_EQ(v[3], 4);
}

TEST(VectorTest, InsertManyFront) {
  s21::vector<int> v = {3, 4};

  v.insert_many_front(1, 2);

  EXPECT_EQ(v.size(), 4);
  EXPECT_EQ(v[0], 1);
  EXPECT_EQ(v[1], 2);
  EXPECT_EQ(v[2], 3);
  EXPECT_EQ(v[3], 4);
}